/*
Streets-TreeComboBox By Jimmy
based on wicket-autocomplete.js
*/
if (typeof(Streets) == "undefined")
	Streets = { };

Streets.TreeComboBox=function(elementId, callbackUrl, cfg, indicatorId,onlySelectLeaf){
    var KEY_TAB=9;
    var KEY_ENTER=13;
    var KEY_ESC=27;
    var KEY_LEFT=37;
    var KEY_UP=38;
    var KEY_RIGHT=39;
    var KEY_DOWN=40;
    var KEY_SHIFT=16;
    var KEY_CTRL=17;
    var KEY_ALT=18;

    var lastSelected = null;
    var selected=null; 	// index of the currently selected item
    var elementCount=0; // number of items on the auto complete list
    var visible=0;		// is the list visible 
    var mouseactive=0;	// is mouse selection active
	var hidingPopup=0;		// are we hiding the popup list

	var isTreePopup=1; //which popup is visibled 1:tree 0:list
	
	// pointers of the browser events
   	var objonkeydown;
	var objonblur;
	var objonkeyup;
	var objonkeypress;
	var objonchange;
	var objonchangeoriginal;
	var objonfocus;
	var icononclick;
	
	var popupContainerId = elementId+"_$Container";
	var popupId = elementId+"_$Popup";
	var treePopupId = elementId+"_$TreePopup";
	var codeElementId = elementId+"_$Id";
	var iconElementId = elementId +"_$Icon";
	
	var clickUrl;
	
	var ajaxChannel = "streets-TreeComboBox|d";
	
    var ignoreOneFocusGain = false; // on FF, clicking an option in the popup would make field loose focus; focus() call only has effect in FF after popup is hidden, so the re-focusing must not show popup again in this case

	// holds a throttler, for not sending many requests if the user types
	// too quickly.
	var localThrottler = new Wicket.Throttler(true);
	var throttleDelay = cfg.throttleDelay;
	
    function getPopup() {
        var popupDiv=wicketGet(isTreePopup?treePopupId:popupId);
        if (popupDiv==null) {
        	var className = cfg.className ? cfg.className : "comboBoxPopup"; 
            
        	var container = document.createElement("div");
            wicketGet(elementId).parentNode.appendChild(container);
            container.className = className + "-container";
            container.style.display="none";
        	container.style.overflow="auto";
            container.style.position="absolute";            
            container.id=popupContainerId;
            	
            container.show = function() { wicketShow(this.id) };
            container.hide = function() { wicketHide(this.id) };
            
            popupDiv=document.createElement("div");
            container.appendChild(popupDiv);
            popupDiv.id=popupId;
            popupDiv.style.display="none";
            popupDiv.className=className;
            
            popupDiv=document.createElement("div");
            container.appendChild(popupDiv);
            popupDiv.id=treePopupId;
            popupDiv.style.display="none";
            popupDiv.className=className;
            
            // WICKET-1350/WICKET-1351
            container.onmouseout=function() {mouseactive=0;};
            container.onmousemove=function() {mouseactive=1;};
        }

        return  wicketGet(isTreePopup?treePopupId:popupId);
    }

    function initIconPosition(){
    	var icon = wicketGet(iconElementId);
    	var iconWidth = icon.offsetWidth;
    	var obj=wicketGet(elementId);    		
    	obj.style.paddingRight = iconWidth;
    	var objPos = getPosition(obj);
    	icon.style.visibility = "visible";
    	setPosition(icon,[objPos[0] + obj.offsetWidth - iconWidth - 1,objPos[1]]); 
    }
    
    function initialize(){
		// Remove the popup if still present from
		// a previous call. This is required to properly register
		// the mouse event handler again (using the new stateful 'mouseactive'
		// variable which just gets created)
        var popupDiv=wicketGet(popupId);
        if (popupDiv != null) {
        	lastSelected = null;
        	selected = null;
            popupDiv.parentNode.parentNode.removeChild(popupDiv.parentNode);
        } 

        var obj=wicketGet(elementId);

        objonkeydown=obj.onkeydown;
        objonblur=obj.onblur;
        objonkeyup=obj.onkeyup;
        objonkeypress=obj.onkeypress;
        objonfocus=obj.onfocus;

        var initIcon = function (){
        	var icon = wicketGet(iconElementId);        
        	clickUrl = icon.getAttribute("clickUrl");
        	initIconPosition();
        	icon["initPos"] = initIconPosition;
        	Wicket.Event.add(icon,"onmouseout",function() {mouseactive=0;});
        	Wicket.Event.add(icon,"onmouseover",function() {mouseactive=1;});
        	icon.onclick=function(event){
        		focusInput();
        		killEvent(event);
        		showIndicator();
        		isTreePopup=1;
    			if (this.getAttribute("showPopup")){
    				if (this.getAttribute("hp")){//haved popup root
    					selected = lastSelected;
    					lastSelected = null;
    					showPopup();
    					render();    	                
    				} else {
    					var request = new Wicket.Ajax.Request(clickUrl, function(r){doUpdateChoices(r,getPopup());expandRoot();icon.setAttribute("hp","1");}, false, true, null, ajaxChannel);
    					request.get();
    				}
    			} else {
    				wicketAjaxGet(clickUrl);
    			}
        	}
        	icononclick = icon.onclick;
        }
        if (obj.offsetWidth > 0){
        	initIcon();
        } else {
        	window.setTimeout(initIcon, 200);
        }
        
        // WICKET-1280
        objonchangeoriginal=obj.onchange; 
        obj.onchange=function(event){
      		if(mouseactive==1)return false;
      		if(typeof objonchangeoriginal=="function"){
      			var code = wicketGet(codeElementId);
      			if (code.getAttribute("i")!=code.value)	objonchangeoriginal.apply(this,[event]);
      			code.setAttribute("i",code.value);
      		}
      	}
        objonchange=obj.onchange;
                
      	obj.onblur=function(event){      		
    		if(mouseactive==1){
                  ignoreOneFocusGain = true;
    			Wicket.$(elementId).focus();
    			return killEvent(event);
    		}
          	hidePopup();
          	if(typeof objonblur=="function")objonblur.apply(this,[event]);
        }
      	
      	obj.onfocus=function(event){
			if (mouseactive==1) return killEvent(event);
            if (!ignoreOneFocusGain){
            	obj.select();
            	if (cfg.showListOnFocusGain) {
            		if (cfg.showCompleteListOnFocusGain) {
            			updateChoices(true);
            		} else {
            			updateChoices();
            		}
            	}
            }
            ignoreOneFocusGain = false;
          	if(typeof objonfocus=="function")objonfocus.apply(this,[event]);
        }

        obj.onkeydown=function(event){
            switch(wicketKeyCode(Wicket.fixEvent(event))){
                case KEY_UP:
                	changeSelected(-1);
            	    if(!selected){
    	           	    hidePopup();
                   	} else {
	                    render();
        	        }
            	    if(Wicket.Browser.isSafari())return killEvent(event);
                	break;
                case KEY_DOWN:
    	            if(visible==0){
    	            	if (this.value!=""){
    	            		updateChoices();
    	            	} else {
    	            		icononclick.apply(wicketGet(iconElementId),[event]);
    	            	}
            	    } else {
                   		changeSelected(1);            	    	
                	    render();
                    	showPopup();
	                }
    	            if(Wicket.Browser.isSafari())return killEvent(event);
        	        break;
                case KEY_ESC:
            	    hidePopup();
                	return killEvent(event);
               		break;
                case KEY_TAB:
                case KEY_ENTER:
                    if(selected) {
                    	if (isTreePopup){
                    		if (!onlySelectLeaf || selected.firstChild.className.indexOf("item") >=0){
                        		setCode();
                        	} else {
                        		focusInput();
                        		hidingPopup = 0;
                        		return killEvent(event);
                        	}
                    	} else {
                    		setCode();
                    	}                    	
                    } else{
                    	setNull();
                    }
                    hidePopup();
                    hidingPopup = 1;
                    mouseactive=0;
                    if(typeof objonchange=="function") objonchange.apply(this,[event]);
	                if(typeof objonkeydown=="function")objonkeydown.apply(this,[event]);
	              
            	    return true;
                break;
                default:
            }
        }

        obj.onkeyup=function(event){
            switch(wicketKeyCode(Wicket.fixEvent(event))){
            	case KEY_TAB:
                case KEY_ENTER:
	                return killEvent(event);
                case KEY_UP:
                case KEY_DOWN:
                case KEY_ESC:
                case KEY_RIGHT:
                case KEY_LEFT:
                case KEY_SHIFT:
                case KEY_ALT:
                case KEY_CTRL:
                break;
                default:
                	if (this.value!=""){
	            		updateChoices();
	            	} else {
	            		icononclick.apply(wicketGet(iconElementId),[event]);
	            	}
            }
			if(typeof objonkeyup=="function")objonkeyup.apply(this,[event]);
            return null;
        }

        obj.onkeypress=function(event){
            if(wicketKeyCode(Wicket.fixEvent(event))==KEY_ENTER){
                if(selected || hidingPopup==1){
			        hidingPopup=0;
			        return killEvent(event);
                }
            }
			if(typeof objonkeypress=="function")objonkeypress.apply(this,[event]);
        }
    }
    
    function changeSelected(f){
    	lastSelected = selected;
    	if (f==-1){
    		if (isTreePopup){
    			if (selected){
    				var p = selected.parentNode;
    				if (p.previousSibling){
    					var tmp = p.previousSibling;
    					while (tmp.firstChild.firstChild.className.indexOf("opened")>=0){
    						tmp = tmp.lastChild.firstChild.lastChild;
    					}
    					selected = tmp ? tmp.firstChild : null;
    				} else {
    					if (p.parentNode.tagName=="UL" && p.parentNode.parentNode.className=="children" && p.parentNode.parentNode.previousSibling){
    						selected = p.parentNode.parentNode.previousSibling;
    					} else {
    						selected = null;
    					}
    				}
    			} 
    		} else {
    			selected = selected ? selected.previousSibling : null;    			
    		}
    	} else{
    		if (selected){
    			var tmp = selected;
    			if (isTreePopup){
    				var p = selected.parentNode;
    				if (selected.firstChild.className.indexOf("opened")>=0){
    					selected = p.lastChild.firstChild ? p.lastChild.firstChild.firstChild.firstChild : tmp;
    				} else {
    					if (p.nextSibling){
    						selected = p.nextSibling.firstChild;
    					} else {
    						if (p.parentNode.tagName=="UL" && p.parentNode.parentNode.className=="children"){
        						p = p.parentNode.parentNode.parentNode.nextSibling;
        						selected = p ? p.firstChild : tmp;
    						} else {
    							selected =tmp;
    						}
    					}
    				}
    			} else {
    				selected = selected.nextSibling ? selected.nextSibling : tmp;
    			}
    		} else {
    			if (isTreePopup){
    				selected = elementCount>0?getPopup().firstChild.childNodes[0].childNodes[0]:null;
    			}else{
    				selected = elementCount>0?getPopup().firstChild.childNodes[0]:null;
    			}
    		}
    	}
    	
    }

    function killEvent(event){
        if(!event)event=window.event;
        if(!event)return false;
        if(event.cancelBubble!=null){
            event.cancelBubble=true;
        }
        if(event.returnValue){
            event.returnValue=false;
        }
        if(event.stopPropagation){
            event.stopPropagation();
        }
        if(event.preventDefault){
            event.preventDefault();
        }
        return false;
    }

    function updateChoices(showAll){
       	selected=null;
       	var isReadOnly = wicketGet(elementId).getAttribute("readonly");
       	if (isReadOnly) return;
        if (showAll) {
            localThrottler.throttle(popupId, throttleDelay, actualUpdateChoicesShowAll);
        } else {
            localThrottler.throttle(popupId, throttleDelay, actualUpdateChoices);
        }
    }

    function actualUpdateChoicesShowAll()
    {
    	showIndicator();
       	var request = new Wicket.Ajax.Request(callbackUrl+"&q=", doUpdateChoices, false, true, null,ajaxChannel);
       	request.get();
    }

    function actualUpdateChoices()
    {
    	showIndicator();
        var value = wicketGet(elementId).value;
       	var request = new Wicket.Ajax.Request(callbackUrl+(callbackUrl.indexOf("?")>-1 ? "&" : "?") + "q="+processValue(value), doUpdateChoices, false, true, null, ajaxChannel); 
       	request.get();
    }
    
    function showIndicator() {
    	if (indicatorId!=null) {
    		Wicket.$(indicatorId).style.display='';
    	}
    }
    
    function hideIndicator() {
    	if (indicatorId!=null) {
    		Wicket.$(indicatorId).style.display='none';
    	}
    }
    
    function processValue(param) {
        return (encodeURIComponent)?encodeURIComponent(param):escape(param);
    }

    function showPopup(){
        var position=getPosition(wicketGet(elementId));
        var container = getPopup().parentNode;
        var input=wicketGet(elementId);
        container.style.zIndex=100;
        if(cfg.adjustInputWidth){
        	container.style.width=input.offsetWidth + 'px';
        }
        if (isTreePopup){
        	if (wicketGet(popupId).style.display != "none" ) {
        		container.scrollTop = 0;
        		container.scrollLeft = 0;
        	}
        	wicketHide(popupId);
        	wicketShow(treePopupId);
        } else {
        	if (wicketGet(treePopupId).style.display != "none" ) {
        		container.scrollTop = 0;
        		container.scrollLeft = 0;
        	}
        	wicketHide(treePopupId);
        	wicketShow(popupId);
        }
        container.show();
        setPosition(container,[position[0],position[1]+input.offsetHeight]);
        visible=1;
    }

    function hidePopup(){
        visible=0;
        if (selected){
        	var re = /\bselected\b/gi;
        	selected.className =  selected.className.replace(re,"");
        }
        selected=null;

        getPopup().parentNode.hide();
        
        var code = wicketGet(codeElementId);
        var element = wicketGet(elementId);
        var text = code.getAttribute("t");
        if (element.value!=text){
        	element.value = text;
        }
    }

    function toInt(s){
    	var v = parseInt(s);
    	return v ? v : 0;
    }
    
    function getPosition(obj) {
		var box = obj.getBoundingClientRect();
	    var doc = obj.ownerDocument;
	    var scrollLeft =Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft);
	    var scrollTop = Math.max(doc.documentElement.scrollTop,doc.body.scrollTop);
	    var xy = [box.left, box.top];
	        
	    if (Wicket.Browser.isIE()){
	        var index = navigator.userAgent.indexOf("MSIE");
	    	var version = parseFloat(navigator.userAgent.substring(index + 5));
	    	if (version<8){
	    		var off1=2;
	    		var off2 =2;
	    		var bLeft = getStyle(doc.documentElement,"borderLeftWidth");
	    		var bTop = getStyle(doc.documentElement,"borderTopWidth");
	            if (bLeft !== "medium") off1 = parseInt(bLeft, 10);
	            if (bTop !== "medium") off2 = parseInt(bTop, 10);
	            xy[0] -= off1;
	            xy[1] -= off2;
	        }            
	    }
	    if ((scrollTop || scrollLeft)) {
	       xy[0] += scrollLeft;
	       xy[1] += scrollTop;
	    }
	    return xy;	    
    }
	 
	function setPosition(obj,xy,noRetry){
		var delta = [parseInt(getStyle(obj,"left"), 10), parseInt(getStyle(obj,"top"), 10 )];
		if ( isNaN(delta[0]) ) delta[0] = obj.offsetLeft;
		if ( isNaN(delta[1]) ) delta[1] = obj.offsetTop;
		var currentXY = getPosition(obj);

		if (xy[0] !== null) obj.style.left = xy[0] - currentXY[0] + delta[0] + 'px';
		if (xy[1] !== null) obj.style.top = xy[1] - currentXY[1] + delta[1] + 'px';
		if (!noRetry){
			var newXY = getPosition(obj);
			if ( (xy[0] !== null && newXY[0] != xy[0]) || 
				(xy[1] !== null && newXY[1] != xy[1]) ) {
				setPosition(obj, xy,true);
			}
		}
	}
	function iconClickFunc(event){
		focusInput();
		killEvent(event);
		isTreePopup = 1;
		var p = this.parentNode.nextSibling;
		if (this.className=="closed"){
			p.style.display = "block";			
			if(p.childNodes.length==0){
				generateChildren(p);
			}
			this.className = "opened";
		} else {
			this.className = "closed";
			wicketHide(p);
		}
	}
	function generateChildren(p){
		var updateNodes = function(resp){	
			doUpdateChoices(resp,p);
		}
		var request = new Wicket.Ajax.Request(clickUrl+"&p="+p.previousSibling.getAttribute("i"), updateNodes, false, true, null, ajaxChannel);
        request.get();
	}
	function focusInput(){
		var input = wicketGet(elementId)
		if (Wicket.Focus.getFocusedElement() != input ){
            ignoreOneFocusGain = true;
            input.focus();
        }
	}
	function expandRoot(){
		var element = getPopup();
		if (element.childNodes.length >0){
			element = element.childNodes[0];
			if (element.childNodes.length==1){
				var node = element.childNodes[0];
				if (node && node.firstChild.tagName=="DIV" && node.childNodes.length==2)	node.firstChild.firstChild.onclick();
			}
		}
	}
	
    function doUpdateChoices(resp,pElement){
    	lastSelected = selected;
    	selected=null;
    	// check if the input hasn't been cleared in the meanwhile
    	var input=wicketGet(elementId); 
    	if ((Wicket.Focus.getFocusedElement() != input) || (!cfg.showListOnEmptyInput && (input.value==null || input.value==""))) {
   			hidePopup();
   			Wicket.Ajax.invokePostCallHandlers();
   			hideIndicator();
   			return;
   		}
   		isTreePopup = pElement ? 1 : 0;   		
   		var element = !pElement ? getPopup() : pElement;
        element.innerHTML=resp;
        if(element.firstChild && element.firstChild.childNodes.length>0) {
        	elementCount=element.firstChild.childNodes.length;

        	var clickFunc = function(event){
        		mouseactive=0;
        		setCode();
        		if (typeof objonchange=="function") {objonchange.apply(wicketGet(elementId), [event]);}
        		hidePopup();
                if (Wicket.Focus.getFocusedElement() != input){
                    ignoreOneFocusGain = true;
                    input.focus();
                }
        	};
			
        	var mouseOverFunc = function(event){
                mouseactive=1; // Opera needs this as mousemove for popup is not always triggered
                lastSelected = selected;
                selected = this;
                render();
                showPopup();
        	};

        	var parentNode = element.firstChild;
        	for(var i = 0;i < elementCount; i++) {
        		var node = parentNode.childNodes[i];
        		if (pElement){
        			node.firstChild.onmouseover = mouseOverFunc;
        			if (!onlySelectLeaf || node.childNodes.length==1)	node.firstChild.onclick = clickFunc;
        			if (node.firstChild.tagName=="DIV" && node.childNodes.length==2)	node.firstChild.firstChild.onclick = iconClickFunc;				
        		} else {	
        			node.onclick = clickFunc;
        			node.onmouseover = mouseOverFunc;
        		}
      		}
        } else {
            elementCount=0;
            element.innerHTML="<ul><a/></ul>";
        }
        
        if(elementCount>0 && cfg.preselect==true){
        	selected = getPopup().firstChild.childNodes[0];
        }
        
       	showPopup();
        render();
        
        Wicket.Log.info("Response processed successfully.");
        Wicket.Ajax.invokePostCallHandlers();
        hideIndicator();
    }

    function setCode(){
    	var code = wicketGet(codeElementId);
    	var id = selected.getAttribute("i");
    	var text = stripHTML(selected.innerHTML);
    	code.value = id;
    	code.setAttribute("t",text);
    	wicketGet(elementId).value = text;
    }
    
    function setNull(){
    	var code = wicketGet(codeElementId);
    	var element = wicketGet(elementId);
    	if (element.getAttribute("r")!="1"&&element.value.replace(/^\s+|\s+$/g, '')==""){
    		code.value="";
    		code.setAttribute("t","");
    		element.value = "";
    	}
    }

    function stripHTML(str) {
        return str.replace(/<[^>]+>/g,"").replace("&nbsp;","").replace("\\\"", "&#34;");
    }
    
    function adjustScrollOffset(container, item) { 
    	if (isTreePopup){
			var topPosition = item.offsetTop || 0;
	    	var leftPosition = item.offsetLeft || 0;

    		try{
    	        var tmp = item.offsetParent;
    	        while (tmp && tmp != container) {
    	            topPosition += tmp.offsetTop || 0;
    	     		topPosition -= tmp.scrollTop || 0;
    	     		leftPosition += tmp.offsetLeft || 0;
    	      		leftPosition -= tmp.scrollLeft || 0;
    	            tmp = tmp.offsetParent;
    	        }
    	        if (topPosition + item.offsetHeight > container.scrollTop + container.clientHeight) {
            		container.scrollTop = topPosition + item.offsetHeight - container.clientHeight;
        		} else
        		// adjust to the top
        		if (topPosition < container.scrollTop) {
        			container.scrollTop = topPosition;
        		}
            	if (leftPosition+ item.offsetWidth > container.scrollLeft+ container.clientWidth) {
            		container.scrollLeft = leftPosition + item.offsetWidth - container.clientWidth;
            	}
            	if (leftPosition < container.scrollLeft) {
        			container.scrollLeft = leftPosition;
        		}
    		}catch(ex){}    			
    	} else {
    		if (item.offsetTop + item.offsetHeight > container.scrollTop + container.clientHeight) {
        		container.scrollTop = item.offsetTop + item.offsetHeight - container.clientHeight;
    		} else
    		// adjust to the top
    		if (item.offsetTop < container.scrollTop) {
    			container.scrollTop = item.offsetTop;
    		}
    	}
    	 	
    }

    function render(){
        var popup=getPopup();
        var re = /\bselected\b/gi;
        if (lastSelected){
			lastSelected.className =  lastSelected.className.replace(re,"");
		}
        if (selected){
        	selected.className = selected.className + " selected";
        	adjustScrollOffset(popup.parentNode, selected);
        }
        if (cfg.maxHeight > -1) {
        	if (popup.offsetHeight<cfg.maxHeight) {
                popup.parentNode.style.height="auto";
            } else {
        	    popup.parentNode.style.height=cfg.maxHeight+"px";
            }
        }
    }
    
    // From http://www.robertnyman.com/2006/04/24/get-the-rendered-style-of-an-element/
    function getStyle(obj,cssRule) {
    	var cssRuleAlt = cssRule.replace(/\-(\w)/g,function(strMatch,p1){return p1.toUpperCase();});
        var value=obj.style[cssRuleAlt];
        if (!value) {
	        if (document.defaultView && document.defaultView.getComputedStyle) {
	            value = document.defaultView.getComputedStyle(obj,"").getPropertyValue(cssRule);
	        }
	        else if (obj.currentStyle)
	        {
	            value=obj.currentStyle[cssRuleAlt];
	        }
        }
        return value;
    }

    initialize();
}
